package com.xx.netty;


import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author ruby
 * @create 2023-11-06 10:08 AM
 */
@Slf4j
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    public static NettyServerHandler nettyServerHandler;

    public static Map<String, ChannelHandlerContext> ctxMap = new ConcurrentHashMap<String, ChannelHandlerContext>(16);

    @PostConstruct
    public void init() {
        nettyServerHandler = this;

        // 初使化时将已静态化的testService实例化
    }

    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctxMap.put(ctx.channel().remoteAddress().toString(),ctx);
        System.out.println("连接的客户端地址:" + ctx.channel().remoteAddress());
        log.info("连接成功...");
        //开辟新的线程处理 从Scanner中获取消息给客户端发送消息
        new Thread(new Runnable() {
            @Override
            public void run() {
                String keyid = null;
                while (true) {
                    Scanner scanner = new Scanner(System.in);
                    String msg = scanner.nextLine();
                    if(msg.equals("list")){
                        for(String key : ctxMap.keySet()){
                            System.out.println(key);
                        }
                        continue;
                    }
                    if(keyid == null || "".equals(keyid)){
                        try {
                            keyid = ctxMap.get(msg).channel().remoteAddress().toString();
                        }catch (Exception e){
                            System.out.println("请输入正确的keyid"+ctxMap.keySet().toString());
                        }
                        continue;
                    }
                    if(msg.equals("exit")){
                        keyid = null;
                        continue;
                    }
                    if(msg.equals("keyId")){
                        System.out.println(keyid);
                        continue;
                    }
                    if (msg != null && !"".equals(msg)) {
                        //tcp 如果是AT指令自动加回车换行
                        if(msg.indexOf("AT") > -1){
                            msg = stringToHexString(msg).toUpperCase()+"0D0A";
                            //HEX转String
                            msg = hexStringToString(msg);
                        }

                        if ((msg.replaceAll(" ","").indexOf("EFFF") > -1||msg.replaceAll(" ","").indexOf("EFAA") > -1)&&msg.replaceAll(" ","").indexOf("EF55") > -1) {
                            msg = msg.replaceAll(" ","");
                            System.out.println(msg);
                            byte[] bytes = hexToByteArray(msg);
                            sendMessageByte(keyid, Unpooled.copiedBuffer(bytes));
                            continue;
                        }
                        sendMessageStr(keyid,msg);
                    }
                }
            }
        }).start();

    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        if (msg instanceof ByteBuf) {
            ByteBuf byteBuf = (ByteBuf) msg;
            try {
                byte[] dataBytes = new byte[byteBuf.readableBytes()];
                byteBuf.readBytes(dataBytes);
                // 将字节数据转换为十六进制字符串
                String hexData = bytesToHex(dataBytes);
                // 将字节数组转换为字符串，使用UTF-8编码
                String str = new String(dataBytes, StandardCharsets.UTF_8);
                log.info("服务器收到消息: {} 源：{}", hexData,str);
                // 在这里可以根据需要回复客户端
                ctx.write("收到你的消息："+hexData + "  " + str);
                ctx.flush();
                // ...
            } finally {
                byteBuf.release();
            }
//        }
//
//        ctx.write("收到你的消息："+msg);
//        ctx.flush();
    }


    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        removeChannelMap(ctx);
        super.channelInactive(ctx);
    }

    /**
     * 移除已经失效的链接
     * @param ctx
     */
    private void removeChannelMap(ChannelHandlerContext ctx) {
        for( String key :ctxMap.keySet()){
            if(ctxMap.get(key)!=null && ctxMap.get(key).equals(ctx)){
                ctxMap.remove(key);
            }
        }
    }

    public void sendMessageByte(String keyid, ByteBuf message){
        ChannelHandlerContext ctx = ctxMap.get(keyid);
        //对信息进行hex
        ctx.write(message);
        ctx.flush();
        //writeAndFlush在这里没生效，没找到原因
    }
    public void sendMessageStr(String keyid,String message){
        ChannelHandlerContext ctx = ctxMap.get(keyid);
        //对信息进行hex
        ctx.write(message);
        ctx.flush();
        //writeAndFlush在这里没生效，没找到原因
    }
    public static String stringToHexString(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return str;
    }

    /**
     * 十六进制转换为十进制
     *
     * @param content
     * @return
     */
    public static int covert(String content) {
        int number = 0;
        String[] HighLetter = {"A", "B", "C", "D", "E", "F"};
        Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i <= 9; i++) {
            map.put(i + "", i);
        }
        for (int j = 10; j < HighLetter.length + 10; j++) {
            map.put(HighLetter[j - 10], j);
        }
        String[] str = new String[content.length()];
        for (int i = 0; i < str.length; i++) {
            str[i] = content.substring(i, i + 1);
        }
        for (int i = 0; i < str.length; i++) {
            number += map.get(str[i]) * Math.pow(16, str.length - 1 - i);
        }
        return number;
    }

    /**
     * 十进制转换为ASCII码
     *
     * @param ascii
     * @return
     */
    public static String dec2Str(String ascii) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < ascii.length() - 1; i += 2) {
            String h = ascii.substring(i, (i + 2));
            // 这里第二个参数传10表10进制
            int decimal = Integer.parseInt(h, 10);
            sb.append((char) decimal);
        }
        return sb.toString();
    }

    /**
     * Hex字符串转byte
     * @param inHex 待转换的Hex字符串
     * @return  转换后的byte
     */
    public static byte hexToByte(String inHex){
        return (byte)Integer.parseInt(inHex,16);
    }

    /**
     * hex字符串转byte数组
     *
     * @param inHex 待转换的Hex字符串
     * @return 转换后的byte数组结果
     */
    public static byte[] hexToByteArray(String inHex){
        int hexlen = inHex.length();
        byte[] result;
        if (hexlen % 2 == 1){
            //奇数
            hexlen++;
            result = new byte[(hexlen/2)];
            inHex="0"+inHex;
        }else {
            //偶数
            result = new byte[(hexlen/2)];
        }
        int j=0;
        for (int i = 0; i < hexlen; i+=2){
            result[j]=hexToByte(inHex.substring(i,i+2));
            j++;
        }
        return result;
    }

    /**
     * Hex字符串转String
     * @param src
     * @return
     */
    public static String hexStringToString(String src) {
        String temp = "";
        for (int i = 0; i < src.length() / 2; i++) {
            temp = temp + (char) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return temp;
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            hexString.append(String.format("%02X", b));
        }
        return hexString.toString();
    }
}

